<!--
> Muaz Khan     - https://github.com/muaz-khan 
> MIT License   - https://www.webrtc-experiment.com/licence/
> Documentation - https://github.com/muaz-khan/WebRTC-Experiment/tree/master/meeting
-->
<!DOCTYPE html>
<html lang="en">
    <head>
        <script>
            if(!location.hash.replace('#', '').length) {
                location.href = location.href.split('#')[0] + '#' + (Math.random() * 100).toString().replace('.', '');
                location.reload();
            }
        </script>

        <title>Meeting.js » A WebRTC Library for Media Streaming | Muaz Khan</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
        <link rel="author" type="text/html" href="https://plus.google.com/+MuazKhan">
        <meta name="author" content="Muaz Khan">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <link rel="stylesheet" href="https://www.webrtc-experiment.com/style.css">
        <style>
            audio, video {
                width: 100%;
                vertical-align:top;
            }
            input {
                font-size: 2em;
                width: 4em;
            }
            
            p { padding: 1em; }
        </style>
        <script>
            document.createElement('article');
            document.createElement('footer');
        </script>
        
        <!-- Meeting.js library -->
        <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
        <script src="https://www.webrtc-experiment.com/CodecsHandler.js"></script>
        <script src="https://www.webrtc-experiment.com/IceServersHandler.js"></script>
        <script src="https://www.webrtc-experiment.com/meeting.js"> </script>
    </head>

    <body>
        <article>
            <header style="text-align: center;">
                <h1>
                    <a href="https://github.com/muaz-khan/WebRTC-Experiment/tree/master/meeting" target="_blank">Meeting.js </a>
                    » A <a href="https://www.webrtc-experiment.com/">WebRTC</a> Library for Media Streaming
                </h1>            
                <p>
                    <a href="https://www.webrtc-experiment.com/">HOME</a>
                    <span> &copy; </span>
                    <a href="http://www.MuazKhan.com/" target="_blank">Muaz Khan</a>
                    
                    .
                    <a href="http://twitter.com/WebRTCWeb" target="_blank" title="Twitter profile for WebRTC Experiments">@WebRTCWeb</a>
                    
                    .
                    <a href="https://github.com/muaz-khan?tab=repositories" target="_blank" title="Github Profile">Github</a>
                    
                    .
                    <a href="https://github.com/muaz-khan/WebRTC-Experiment/issues?state=open" target="_blank">Latest issues</a>
                    
                    .
                    <a href="https://github.com/muaz-khan/WebRTC-Experiment/commits/master" target="_blank">What's New?</a>
                </p>
            </header>

            <div class="github-stargazers"></div>
        
            <!-- just copy this <section> and next script -->
            <section class="experiment">
                <section>
                    <h2 style="border: 0; padding-left: .5em;">Wanna try yourself?</h2>
                    <input type="text" id="meeting-name">
                    <button id="setup-meeting">Setup New Meeting</button>
                </section>

                <table style="width: 100%;" id="meetings-list"></table>
                <table style="width: 100%;">
                    <tr>
                        <td style="width: auto!important;">
                            <h2 style="display: block; font-size: 1em; text-align: center;">You!</h2>
                            <div id="local-streams-container"></div>
                        </td>
                        <td style="background: white;width: auto!important;">
                            <h2 style="display: block; font-size: 1em; text-align: center;">Remote Peers</h2>
                            <div id="remote-streams-container"></div>
                        </td>
                    </tr>
                </table>
            </section>
        
            <script>
                var meeting = new Meeting();

                var meetingsList = document.getElementById('meetings-list');
                var meetingRooms = {};
                meeting.onmeeting = function (room) {
                    if (meetingRooms[room.roomid]) return;
                    meetingRooms[room.roomid] = room;

                    var tr = document.createElement('tr');
                    tr.innerHTML = '<td>' + room.roomid + '</td>' +
                        '<td><button class="join">Join</button></td>';

                    meetingsList.insertBefore(tr, meetingsList.firstChild);

                    // when someone clicks table-row; joining the relevant meeting room
                    tr.onclick = function () {
                        room = meetingRooms[room.roomid];

                        // manually joining a meeting room
                        if (room) meeting.meet(room);

                        meetingsList.style.display = 'none';
                    };
                };

                var remoteMediaStreams = document.getElementById('remote-streams-container');
                var localMediaStream = document.getElementById('local-streams-container');

                // on getting media stream
                meeting.onaddstream = function (e) {
                    if (e.type == 'local') localMediaStream.appendChild(e.video);
                    if (e.type == 'remote') remoteMediaStreams.insertBefore(e.video, remoteMediaStreams.firstChild);
                };
                
                // via: https://github.com/muaz-khan/WebRTC-Experiment/tree/master/websocket-over-nodejs
                meeting.openSignalingChannel = function(onmessage) {
                    var channel = location.href.replace(/\/|:|#|%|\.|\[|\]/g, '');
                    var websocket = new WebSocket('wss://websocket-over-nodejs.herokuapp.com:443/');
                    websocket.onopen = function () {
                        websocket.push(JSON.stringify({
                            open: true,
                            channel: channel
                        }));
                    };
                    websocket.push = websocket.send;
                    websocket.send = function (data) {
                        if(websocket.readyState != 1) {
                            return setTimeout(function() {
                                websocket.send(data);
                            }, 300);
                        }
                        
                        websocket.push(JSON.stringify({
                            data: data,
                            channel: channel
                        }));
                    };
                    websocket.onmessage = function(e) {
                        onmessage(JSON.parse(e.data));
                    };
                    return websocket;
                };

                // using firebase for signaling
                // meeting.firebase = 'muazkh';

                // if someone leaves; just remove his video
                meeting.onuserleft = function (userid) {
                    var video = document.getElementById(userid);
                    if (video) video.parentNode.removeChild(video);
                };

                // check pre-created meeting rooms
                meeting.check();

                document.getElementById('setup-meeting').onclick = function () {
                    // setup new meeting room
                    var meetingRoomName = document.getElementById('meeting-name').value || 'Simple Meeting';
                    meeting.setup(meetingRoomName);
                    
                    this.disabled = true;
                    this.parentNode.innerHTML = '<h2><a href="' + location.href + '" target="_blank">Share this link</a></h2>';
                };
            </script>
            
            <section class="experiment">
                <ol>
                    <li>Mesh networking model is implemented to open multiple peer connections i.e. interconnected peer connections</li>
                    <li>Maximum peer connections limit in mesh-networking is <strong>256</strong> (on chrome)</li>
                </ol>
            </section>
            
            <section class="experiment">
                <h2 class="header">How to use Meeting.js?</h2>
                <pre>
&lt;script src="https://webrtc.github.io/adapter/adapter-latest.js"&gt;&lt;/script&gt;
&lt;script src="https://www.webrtc-experiment.com/CodecsHandler.js"&gt;&lt;/script&gt;
&lt;script src="https://www.webrtc-experiment.com/IceServersHandler.js"&gt;&lt;/script&gt;
&lt;script src="https://www.webrtc-experiment.com/meeting.js"&gt;&lt;/script&gt;
</pre>
                <pre>
var meeting = new Meeting('meeting-unique-id');

// on getting local or remote streams
meeting.onaddstream = function(e) {
    // e.type == 'local' ---- it is local media stream
    // e.type == 'remote' --- it is remote media stream
    document.body.appendChild(e.video);
};

// custom signaling channel
// you can use each and every signaling channel
// any websocket, socket.io, or XHR implementation
// any SIP server
// anything! etc.
meeting.openSignalingChannel = function(callback) {
    return io.connect().on('message', callback);
};

// check pre-created meeting rooms
// it is useful to auto-join
// or search pre-created sessions
meeting.check('meeting room name');

document.getElementById('setup-new-meeting').onclick = function() {
    meeting.setup('meeting room name');
};

// if someone leaves; just remove his video
meeting.onuserleft = function(userid) {
    var video = document.getElementById(userid);
    if(video) video.parentNode.removeChild(video);
};

// to leave a meeting room
meeting.leave();
</pre>
            </section>
            
            <section class="experiment">
                <h2 class="header">How it works?</h2>
                <p><strong>
                    Huge bandwidth and CPU-usage out of multi-peers and number of RTP-ports
                </strong>
                </p>
                <p>
                    To understand it better; assume that 10 users are sharing video in a group.
                    40 RTP-ports i.e. streams will be created for each user. All streams are expected
                    to be flowing concurrently; which causes blur video experience and audio lose/noise (echo)
                    issues.</p>
                <p>
                    For each user:</p>
                <ol>
                    <li>10 RTP ports are opened to send video upward i.e. for outgoing video streams</li>
                    <li>10 RTP ports are opened to send audio upward i.e. for outgoing audio streams</li>
                    <li>10 RTP ports are opened to receive video i.e. for incoming video streams</li>
                    <li>10 RTP ports are opened to receive audio i.e. for incoming audio streams</li>
                </ol>
                <p>
                    Maximum bandwidth used by each video RTP port (media-track) is about 1MB; which can be controlled using "b=AS" session description parameter values. In two-way video-only session; 2MB bandwidth is used by each peer; otherwise; a low-quality blurred video will be delivered.
                </p>
                <pre>
// removing existing bandwidth lines
sdp = sdp.replace( /b=AS([^\r\n]+\r\n)/g , '');

// setting "outgoing" audio RTP port's bandwidth to "50kbit/s"
sdp = sdp.replace( /a=mid:audio\r\n/g , 'a=mid:audio\r\nb=AS:50\r\n');

// setting "outgoing" video RTP port's bandwidth to "256kbit/s"
sdp = sdp.replace( /a=mid:video\r\n/g , 'a=mid:video\r\nb=AS:256\r\n');
</pre>
                <p>
                    Possible issues:</p>
                <ol>
                    <li>Blurry video experience</li>
                    <li>Unclear voice and audio lost</li>
                    <li>Bandwidth issues / slow streaming / CPU overwhelming</li>
                </ol>
                <p>Solution? Obviously a media server!</p>
            </section>
            
            <section class="experiment">
                <h2 class="header">Suggestions</h2>
                <ol>
                    <li>
                        <a href="http://www.RTCMultiConnection.org/" target="_blank">RTCMultiConnection.js</a> can be used for HD screen sharing; HD audio/video streaming; fastest file sharing; and writing entire skype-like app in the browser!
                    </li>
                </ol>
            </section>
        
            <section class="experiment">
                <h2 class="header" id="feedback">Feedback</h2>
                <div>
                    <textarea id="message" style="border: 1px solid rgb(189, 189, 189); height: 8em; margin: .2em; outline: none; resize: vertical; width: 98%;" placeholder="Have any message? Suggestions or something went wrong?"></textarea>
                </div>
                <button id="send-message" style="font-size: 1em;">Send Message</button><small style="margin-left: 1em;">Enter your email too; if you want "direct" reply!</small>
            </section>
            
            <section class="experiment own-widgets latest-commits">
                <h2 class="header" id="updates" style="color: red; padding-bottom: .1em;"><a href="https://github.com/muaz-khan/WebRTC-Experiment/commits/master" target="_blank">Latest Updates</a></h2>
                <div id="github-commits"></div>
            </section>
            
        </article>
        
        <a href="https://github.com/muaz-khan/WebRTC-Experiment/tree/master/meeting" class="fork-right"></a>
        
        <footer>
            <p>
                <a href="https://www.webrtc-experiment.com/">WebRTC Experiments</a>
                © <a href="https://plus.google.com/+MuazKhan" rel="author" target="_blank">Muaz Khan</a>
                <a href="mailto:muazkh@gmail.com" target="_blank">muazkh@gmail.com</a>
            </p>
        </footer>
    
        <!-- commits.js is useless for you! -->
        <script src="https://www.webrtc-experiment.com/commits.js" async> </script>
    </body>
</html>
